﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using DC2010;
using DC2010.Objects.Base;
using DC2010.Objects.Common;
using DC2010.Objects.Data;
using DC2010.Objects.Structures;
using DC2010_EditorData;
using SdlDotNet.Core;
using SdlDotNet.Graphics;
using SdlDotNet.Graphics.Sprites;
using SdlDotNet.Input;
using DC2010.Objects;
using System.Windows.Forms;

namespace DC2012
{
    public partial class CoreEditor : IDisposable
    {
        #region Fields
        private Surface screen; //video screen

        /// <summary>
        /// Holds all sprited which should be removed with time or action. In ideal scenario ... empty
        /// Displayed EVERYTIME
        /// </summary>
        private SpriteCollection master = new SpriteCollection(); 

        /// <summary>
        /// It holds GFX which is visible ALL the time.
        /// </summary>
        private SpriteCollection gameinterface = new SpriteCollection();

        /// <summary>
        /// Just for cursor...
        /// </summary>
        private SpriteCollection cursorinterface = new SpriteCollection();

        /// <summary>
        /// Map
        /// </summary>
        private SpriteCollection map = new SpriteCollection();
		
        private SpriteCollection txtColl = new SpriteCollection(); //holds all sprites
        private SpriteCollection txtColl2 = new SpriteCollection(); //holds all sprites



        /// <summary>
        /// Inventory specific stuff.
        /// </summary>
        private SpriteCollection corridor = new SpriteCollection(); //holds all sprites

        private List<string> DisplayedLayer = new List<string>();

        private int width = 1100; //screen width
        private int height = 600; //screen height
        //string filePath = Path.Combine("..", "..");
        private Surface background;


        private AnimationCollection ac = new AnimationCollection();

        private string ActiveMap = "FLOOR_EDITOR_TEST";

        #endregion Fields

        #region EventHandler Methods

        Collection<Rectangle> rects = new Collection<Rectangle>();

        //A ticker is running to update the sprites constantly.
        //This method will fill the screen with black to clear it of the sprites.
        //Then it will Blit all of the sprites to the screen.
        //Then it will refresh the screen and display it.
        private void Tick(object sender, TickEventArgs args)
        {
            screen.Erase(new Rectangle(0,0,width, height), background );
			screen.Erase(txtColl, background);			
            screen.Erase(master, background);
            //screen.Erase(gameinterface, background);
            screen.Erase(cursorinterface, background);

            txtColl.Clear();

            foreach (string s in DisplayedLayer)
            {
                switch (s)
                {
                    case "SCREEN_INTERFACE":
                        {
                            //ConstructInterface();
                            
                            ConstructMenu();
                            screen.Blit(gameinterface);
                            screen.Blit(txtColl2);
                            break;
                        }
                    case "SCREEN_CORRIDOR":
                        {
                            ConstructCorridor();
                            screen.Blit(corridor);
                            break;
                        }
                    case "SCREEN_STATISTICS":
                        {
                            ConstructStatistics(args.Fps.ToString());
                            screen.Blit(txtColl);
                            break;
                        }

                    case "SCREEN_MAP":
                        {
                            ConstructMap();
                            screen.Blit(map);
                            break;
                        }
                    case "SCREEN_CURSOR":
                        {
                            ConstructCursor();
                            screen.Blit(cursorinterface);
                            break;
                        }
                }                
            }

            screen.Blit(master);
            screen.Update();
        }



        private void ConstructCorridor()
        {

        }
        public Point GetMapCoordinates()
        {
            int X = Mouse.MousePosition.X;
            int Y = Mouse.MousePosition.Y;

            int newX = (X - mapOriginX) / 16;
            int newY = (Y - mapOriginY) / 16;

            return new Point(newX, newY);

        }

        public Point GetMapCoordinates(int X, int Y)
        {
            int newX = (X - mapOriginX) / 16;
            int newY = (Y - mapOriginY) / 16;

            return new Point(newX, newY);
        }

        SdlDotNet.Graphics.Font fuente = new SdlDotNet.Graphics.Font("Erasdemi.ttf", 12);
        private TextSprite ts = null;
        private TextSprite tsx = null;
        private void DisplayText(int X, int Y, string txt, SpriteCollection coll)
        {
            tsx = new TextSprite(txt, fuente, Color.Black, new Point(X + 1, Y + 1));
            txtColl.Add(tsx);

            ts = new TextSprite(txt, fuente, Color.White, new Point(X, Y));
            coll.Add(ts);
        }

        private void AddSprite(DCAnimatedSprite s, SpriteCollection coll)
        {
            var y = (from x in coll where (x is DCAnimatedSprite)&&((DCAnimatedSprite)x).Id == s.Id select x).FirstOrDefault();

            if (y == null)
                coll.Add(s);
        }

        private void RemoveSprite(Sprite s, SpriteCollection coll)
        {
            var y = (from x in coll where x == s select x).FirstOrDefault();

            if (y != null)
                coll.Remove(s);
        }


        private void Quit(object sender, QuitEventArgs e)
        {
            Events.QuitApplication();
        }

        void Events_MouseMotion(object sender, MouseMotionEventArgs e)
        {
            if (e.ButtonPressed)
            {
                Events_MouseButtonDown(null, null);
            }

        }

        #endregion EventHandler Methods


        public void Go()
        {
            DisplayedLayer.Add("SCREEN_CORRIDOR");
            DisplayedLayer.Add("SCREEN_INTERFACE");
            DisplayedLayer.Add("SCREEN_MAP");
            DisplayedLayer.Add("SCREEN_STATISTICS");
            DisplayedLayer.Add("SCREEN_CURSOR");

            FloorInfo fi = Root.I.FloorSystem.GetInfo(ActiveMap);
            if (fi==null)
            {
                fi = new FloorInfo();
                fi.Id = "FLOOR_EDITOR_TEST";
                Root.I.FloorSystem.AddInfo(fi);
            }

            PartyInfo pi = Root.I.PartySystem.GetInfo("PARTY_MAIN_PLAYERS");
            PartyData pd = pi.CreateData();

            Root.I.GameSystem.Party = pd;

            background = new Surface(Path.Combine(Environment.CurrentDirectory, Path.Combine(Neocortex.I.DataDirectory, "gfx\\Interface\\BackgroundEditor.png")));

            Video.WindowIcon();
            Video.WindowCaption = "Deep cave";


            screen = Video.SetVideoMode(width, height);
            screen.Blit(background);

            ConstructInterface();

            screen.Update();

            //The collection will respond to mouse button clicks, mouse movement and the ticker.
            master.EnableMouseButtonEvent();
            master.EnableMouseMotionEvent();
            master.EnableTickEvent();

            //hide cursor
            Mouse.ShowCursor = false;

            //These bind the events to the above methods.
            Events.KeyboardDown += KeyboardDown;
            Events.Tick += Tick;
            Events.Quit += Quit;
            Events.MouseMotion += Events_MouseMotion;
            Events.MouseButtonDown += Events_MouseButtonDown;

            //Start the event ticker
            Events.Run();
        }

        private DCAnimatedSprite selectedTile = null;
        private Sprite GetCursorSprite()
        {
            string code = "CURSOR_EDITOR";
            cursorinterface.Clear();

            if (Root.I.GameSystem.ItemInHand != null)
            {
                //we have something in hand
                code = Root.I.GameSystem.ItemInHand.GfxId + "_ICON";
            }

            Sprite cursor = Neocortex.I.GetAnimatedSprite_Simply(code);

            var x = (from i in cursorinterface where i == cursor select i).FirstOrDefault();

            if (x==null) cursorinterface.Add(cursor);


            if (selectedTile!=null)
            {
                AddSprite(selectedTile, cursorinterface);
            }

            return cursor;
        }




        #region IDisposable Members

        private bool disposed;

        /// <summary>
        /// Destroy object
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Destroy object
        /// </summary>
        public void Close()
        {
            Dispose();
        }

        /// <summary>
        /// Destroy object
        /// </summary>

        ~CoreEditor()
        {
            Dispose(false);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    if (background != null)
                    {
                        background.Dispose();
                        background = null;
                    }
                }
                disposed = true;
            }
        }

        #endregion
    }
}
